package cn.hty.mymsg.handler.loadbalance;

import cn.hty.mymsg.handler.loadbalance.annotations.LoadBalancer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@Service
public class ServiceLoadBalancerFactory<T> implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    private final Map<String, ServiceLoadBalancer<T>> serviceLoadBalancerMap = new ConcurrentHashMap<>();
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 选择负载均衡方式
     * @param servers
     * @param loadbalancerStrategy
     * @return
     */
    public List<T> selectService(List<T>servers,String loadbalancerStrategy){
        ServiceLoadBalancer<T> serviceLoadBalancer = serviceLoadBalancerMap.get(loadbalancerStrategy);
        if (Objects.isNull(serviceLoadBalancer)){
            log.error("没有找到对应的负载均衡策略");
            return servers;
        }
        return  serviceLoadBalancer.select(servers);
    }
    @PostConstruct
    private void init(){
        Map<String, Object> serviceMap = this.applicationContext.getBeansWithAnnotation(LoadBalancer.class);
        //遍历获取的带有loadBalancer注解的bean
        serviceMap.forEach((name,service)->{
            if (service instanceof ServiceLoadBalancer){
                //拿到注解
                LoadBalancer LoadBalancer = AopUtils.getTargetClass(service).getAnnotation(LoadBalancer.class);
                //获取注解里面的策略名字
                String loadbalancerStrategy = LoadBalancer.loadbalancer();
                //放入map(通常情况下 实现的负载均衡service与loadBalanceStrategy一一对应)
                serviceLoadBalancerMap.put(loadbalancerStrategy, (ServiceLoadBalancer) service);
            }
        });


    }

}
